package solution

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/util/guid"
	"learn-goframe/internal/repository/xtcloud-file/dao"
	"learn-goframe/internal/repository/xtcloud-file/entity"

	"learn-goframe/internal/model"

	"learn-goframe/internal/service"
)

type sSolution struct{}

func init() {
	service.RegisterSolution(newSolution())
}

func newSolution() *sSolution {
	return &sSolution{}
}

var cacheDir = gfile.Join(gfile.Dir(gfile.Pwd()), "cache")
var cfg, _ = g.Cfg().Get(gctx.New(), "datacloud")
var cfgGeoChat, _ = g.Cfg().Get(gctx.New(), "geoChat")

// SolutionList 查询分页列表
func (s *sSolution) SolutionList(ctx context.Context, in model.SolutionListInput) (out *model.SolutionListOutput, err error) {
	var solutionModel = dao.ProjectSolution.Ctx(ctx)

	out = &model.SolutionListOutput{
		Page: in.Page,
		Size: in.Size,

		List: []*entity.ProjectSolution{},
	}

	if in.Status != 0 {
		solutionModel = solutionModel.Where(dao.ProjectSolution.Columns().Status, in.Status)
	}

	if in.SolutionName != "" {
		solutionModel = solutionModel.WhereLike(dao.ProjectSolution.Columns().SolutionName, `%`+in.SolutionName+`%`)
	}

	if in.CreateUserId != "" {
		solutionModel = solutionModel.Where(dao.ProjectSolution.Columns().CreateUserId, in.CreateUserId)
	}

	if in.StatusExclude != 0 {
		solutionModel = solutionModel.WhereNot(dao.ProjectSolution.Columns().Status, in.StatusExclude)
	}

	// 分页查询
	listModel := solutionModel.Page(in.Page, in.Size).OrderDesc(dao.ProjectSolution.Columns().CreatedAt)

	var list []*entity.ProjectSolution

	// 执行查询
	if err := listModel.Scan(&list); err != nil {
		return out, err
	}

	// 没有数据
	if len(list) == 0 {
		return out, nil
	}

	out.Total, err = solutionModel.Count()
	if err != nil {
		return out, err
	}

	out.List = list
	return out, nil
}

func (s *sSolution) SolutionAdminUpdate(ctx context.Context, in model.SolutionAdminUpdateInput) (out model.SolutionCreateOutput, err error) {
	// 查询
	_, err = s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return out, gerror.New("方案不存在")
	}

	err = dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err = dao.ProjectSolution.
			Ctx(ctx).
			Data(in).
			FieldsEx(dao.ProjectSolution.Columns().Id).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Update()

		return err
	})

	if err != nil {
		return out, err
	}

	return model.SolutionCreateOutput{
		Id: in.Id,
	}, nil
}

func (s *sSolution) SolutionUserUpdate(ctx context.Context, in model.SolutionUserUpdateInput) (out model.SolutionCreateOutput, err error) {
	// 查询
	solution, err := s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return out, gerror.New("方案不存在")
	}

	if solution.Status == 1 || solution.Status == 2 {
		return out, gerror.New("方案已提交, 不能修改")
	}

	err = dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err = dao.ProjectSolution.
			Ctx(ctx).
			Data(in).
			FieldsEx(dao.ProjectSolution.Columns().Id).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Update()

		return err
	})

	if err != nil {
		return out, err
	}

	return model.SolutionCreateOutput{
		Id: in.Id,
	}, nil
}

func (s *sSolution) SolutionUserCreate(ctx context.Context, in model.SolutionUserCreateInput) (out model.SolutionCreateOutput, err error) {
	in.Id = guid.S()

	err = dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err = dao.ProjectSolution.Ctx(ctx).Data(in).Insert()

		return err
	})

	if err != nil {
		return model.SolutionCreateOutput{}, err
	}

	return model.SolutionCreateOutput{
		Id: in.Id,
	}, nil
}

// SolutionDetail 查询详情
func (s *sSolution) SolutionDetail(ctx context.Context, id string) (out *entity.ProjectSolution, err error) {
	out = &entity.ProjectSolution{}
	if err := dao.ProjectSolution.Ctx(ctx).WherePri(id).Scan(&out); err != nil {
		return nil, err
	}

	return out, nil
}

func (s *sSolution) SolutionRollback(ctx context.Context, in model.SolutionSingleIdInput) (err error) {
	// 查询
	solution, err := s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return gerror.New("方案不存在")
	}

	if solution.Status != 1 {
		return gerror.New("方案不是审核中状态, 不能撤回")
	}

	return dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := dao.ProjectSolution.
			Ctx(ctx).
			Data(g.Map{
				"status": 4,
			}).
			FieldsEx(dao.ProjectSolution.Columns().Id).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Update()
		return err
	})
}

func (s *sSolution) SolutionCheck(ctx context.Context, in model.SolutionCheckInput) (err error) {
	// 查询
	solution, err := s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return gerror.New("方案不存在")
	}

	if solution.Status != 1 {
		return gerror.New("方案不是审核中状态, 不能审核")
	}

	return dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := dao.ProjectSolution.
			Ctx(ctx).
			Data(in).
			FieldsEx(dao.ProjectSolution.Columns().Id).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Update()

		return err
	})
}

func (s *sSolution) SolutionSubmit(ctx context.Context, in model.SolutionSingleIdInput) (err error) {
	// 查询
	solution, err := s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return gerror.New("方案不存在")
	}

	if solution.Status != 4 {
		return gerror.New("方案不是未提交状态, 不能提交")
	}

	return dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err := dao.ProjectSolution.
			Ctx(ctx).
			Data(g.Map{
				"status": 1,
			}).
			FieldsEx(dao.ProjectSolution.Columns().Id).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Update()

		return err
	})
}

func (s *sSolution) SolutionDelete(ctx context.Context, in model.SolutionSingleIdInput) (err error) {
	// 查询
	_, err = s.SolutionDetail(ctx, in.Id)
	if err != nil {
		return gerror.New("方案不存在")
	}

	return dao.ProjectSolution.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err = dao.ProjectSolution.
			Ctx(ctx).
			Where(dao.ProjectSolution.Columns().Id, in.Id).
			Delete()

		return err
	})
}
